/**
 * @file pid.h
 * @brief PID controller header file
 * @author 废话文学创始人
 * @version v1.0
 * @date 2024-07-14
 */

#ifndef __PID_H_
#define __PID_H_

#include "main.h"

/**
 * @brief PID error structure
 */
typedef struct
{
    float previous2; /**< Error two steps back (for incremental PID) */
    float previous;  /**< Previous error value */
    float current;   /**< Current error value */
    float integral;  /**< Integral of error */
} PID_Error;

/**
 * @brief PID parameters structure
 */
typedef struct
{
    float kp;                    /**< Proportional gain */
    float ki;                    /**< Integral gain */
    float kd;                    /**< Derivative gain */
    float filter_for_D;          /**< Complementary filter parameter for derivative term */
    float error_tolerance_range; /**< Error threshold for filtering small errors */
    float Gearshift_Integral;    /**< Variable integral gain coefficient */
} PID_Parameter;

/**
 * @brief PID input structure
 */
typedef struct
{
    float target;           /**< Target setpoint value */
    float actual;           /**< Current measured value */
    float actual_previous;  /**< Previous measured value (for derivative) */
    float actual_previous2; /**< Measured value two steps back (for incremental PID) */
} PID_Input;

/**
 * @brief PID output structure
 */
typedef struct
{
    float value;       /**< Current output value */
    float offset;      /**< Output offset for friction compensation */
    float variation;   /**< Output variation (for incremental PID) */
    float upper_limit; /**< Upper saturation limit */
    float D;           /**< Filtered derivative term */
} PID_Output;

/** @brief Callback function type for control output */
typedef void (*Pid_Control)(float);

/** @brief Callback function type for variable integral gain */
typedef float (*Pid_Gearshift_Integral)(float);

/**
 * @brief Main PID controller structure
 */
typedef struct
{
    PID_Input input;                             /**< Input values */
    PID_Output output;                           /**< Output values */
    PID_Parameter parameter;                     /**< PID parameters */
    PID_Error error;                             /**< Error values */
    Pid_Control pidControl;                      /**< Control output callback */
    Pid_Gearshift_Integral pidGearshiftIntegral; /**< Variable integral callback */
} PID;

// Function declarations
void PID_Init(PID *pid, float kp, float ki, float kd, float output_offset,
              float output_upper_limit, float parameter_filter_for_D,
              float error_tolerance_range, Pid_Control pidControl,
              Pid_Gearshift_Integral pidGearshiftIntegral);
void PID_Parameter_Set(PID *pid, float kp, float ki, float kd);
void PID_Target_Set(PID *pid, float target);
float PID_Target_Get(PID pid);
float PID_Output_Get(PID pid);
void PID_Regulation_Position(PID *pid, float actual);
void PID_Regulation_Incremental(PID *pid, float actual);

#endif /* __PID_H_ */
